home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 85 / CD Temático 40 Febrero 2004.iso / DOS / testdisk / src / godmode.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-01-09  |  27.7 KB  |  983 lines

  1. /*
  2.  
  3.     File: godmode.c
  4.  
  5.     Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org>
  6.   
  7.     This software is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.   
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.   
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  */
  22. #define DEBUG 1
  23. #include <ctype.h>      /* toupper, tolower */
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include "types.h"
  27. #include "common.h"
  28. #include "fnctdsk.h"
  29. #include "analyse.h"
  30. #include "lang.h"
  31. #include "godmode.h"
  32. #include "testdisk.h"
  33. #include "fat.h"
  34. #include "ext2.h"
  35. #include "intrface.h"
  36. #include "md.h"
  37. #include "adv.h"
  38. #define RO 1
  39. #define RW 0
  40. static void align_structure(const t_param_disk *disk_car, t_list_part *list_part);
  41. static void init_structure(const t_param_disk *disk_car,t_list_part *list_part, const int debug);
  42. static void init_part_order(t_list_part *list_part);
  43. static void ask_mbr_order(t_param_disk *disk_car,t_list_part *list_part);
  44. static t_list_part *reduce_structure(t_list_part *list_part);
  45. static t_list_part *add_ext_part(t_param_disk *disk_car, t_list_part *list_part, const int max_ext);
  46. static int write_mbr(t_param_disk *disk_car, const t_list_part *list_part, const int ro, const int debug);
  47. static int write_all_log(t_param_disk *disk_car, const t_list_part *list_part, const int ro , const int debug);
  48. static int diff(const unsigned char buffer[SECTOR_SIZE], const unsigned char buffer_org[SECTOR_SIZE]);
  49. static t_list_part *do_recover_cih(t_param_disk *disk_car,t_list_part *list_part,int debug, const int dump_ind);
  50. static int use_backup(t_param_disk *disk_car, const t_list_part *list_part, const int debug,const int dump_ind);
  51.  
  52. static void align_structure(const t_param_disk *disk_car, t_list_part *list_part)
  53. {
  54.   t_list_part *element;
  55.   for(element=list_part;element!=NULL;element=element->next)
  56.   {
  57.     t_CHS end;
  58.     LBA2CHS(disk_car,element->part->lba+element->part->part_size-1,&end);
  59.     end.sector=disk_car->CHS.sector;
  60.     end.head=disk_car->CHS.head;
  61.     element->part->part_size=CHS2LBA(disk_car, &end)-element->part->lba+1;
  62.   }
  63. }
  64.  
  65. static void init_structure(const t_param_disk *disk_car,t_list_part *list_part, const int debug)
  66. {
  67.   /* Reconstruit une structure 
  68.    * nbr_prim nombre de partition primaire
  69.    * end_log_block : partition etendu du block etendu
  70.    * nbr_log_block : nombre de block de partition etendu
  71.    *                    devrait etre 0 ou 1 */
  72.   unsigned int nbr_prim=0, nbr_log_block=0;
  73.   t_list_part *element;
  74.   t_list_part *end_log_block=NULL;
  75.   t_list_part *end_biggest_log_block=NULL;
  76.   unsigned int log_block_size=0,biggest_log_block_size=0;
  77.   t_list_part *new_list_part=NULL;
  78.   /* Create new list */
  79.   for(element=list_part;element!=NULL;element=element->next)
  80.     element->to_be_removed=0;
  81.   for(element=list_part;element!=NULL;element=element->next)
  82.   {
  83.     int to_be_removed=0;
  84.     t_list_part *element2;
  85.     for(element2=element->next;element2!=NULL;element2=element2->next)
  86.       if(element->part->lba+element->part->part_size-1 >= element2->part->lba)
  87.       {
  88.     to_be_removed=1;
  89.     element2->to_be_removed=1;
  90.       }
  91.     if(to_be_removed)
  92.       element->to_be_removed=1;
  93.     if(element->to_be_removed==0)
  94.       new_list_part=insert_new_partition(new_list_part,element->part);
  95.   }
  96.   /* Verify */
  97.   for(element=new_list_part;element!=NULL;element=element->next)
  98.   {
  99.     if(can_be_ext(disk_car,element->part)==0)
  100.     {
  101.       nbr_prim++;
  102.       if((end_log_block!=NULL) && (end_log_block->next==element))
  103.       {
  104.     if(log_block_size>biggest_log_block_size)
  105.     {
  106.       biggest_log_block_size=log_block_size;
  107.       end_biggest_log_block=end_log_block;
  108.     }
  109.     nbr_log_block++;
  110.     end_log_block=NULL;
  111.       }
  112.     }
  113.     else
  114.     {
  115.       log_block_size++;
  116.       end_log_block=element;
  117.     }
  118.   }
  119.   /* Verification */
  120.   if((end_log_block!=NULL) && (end_log_block->next==NULL))
  121.   {
  122.     if(log_block_size>biggest_log_block_size)
  123.     {
  124.       biggest_log_block_size=log_block_size;
  125.       end_biggest_log_block=end_log_block;
  126.     }
  127.     nbr_log_block++;
  128.   }
  129.   if(debug>1)
  130.     ecrit_rapport("\nRes: nbr_prim %u, nbr_log_block %u\n", nbr_prim, nbr_log_block);
  131.   /* Set primary, extended, logical */
  132.   if(nbr_prim+nbr_log_block<=4)
  133.   {
  134.     int set_prim_bootable_done=0;
  135.     for(element=end_biggest_log_block;element&&can_be_ext(disk_car,element->part);element=element->prev)
  136.     {
  137. /*     ecrit_rapport("%p %p %p %d\n",element,element->prev,element->next,element->part->status); */
  138.       element->part->status=STATUS_LOG;
  139.     }
  140.     for(element=new_list_part;element!=NULL;element=element->next)
  141.     {
  142.       if(element->part->status!=STATUS_LOG)
  143.       {
  144.     if(set_prim_bootable_done)
  145.       element->part->status=STATUS_PRIM;
  146.     else
  147.     {
  148.       /* The first primary partition is bootable unless it's a swap */
  149.       if(element->part->upart_type!=UP_LINSWAP)
  150.       {
  151.         element->part->status=STATUS_PRIM_BOOT;
  152.         set_prim_bootable_done=1;
  153.       }
  154.     }
  155.       }
  156.     }
  157.   }
  158.   check_list_part(new_list_part);
  159.   if(test_structure(new_list_part))
  160.   {
  161.     for(element=new_list_part;element!=NULL;element=element->next)
  162.       element->part->status=STATUS_DELETED;
  163.   }
  164.   {
  165.     /* free */
  166.     t_list_part *new_element;
  167.     for(element=new_list_part;element!=NULL;element=new_element)
  168.     {
  169.       new_element=element->next;
  170.       FREE(element);
  171.     }
  172.   }
  173.   check_list_part(list_part);
  174. }
  175.  
  176. void only_one_bootable( t_list_part *list_part, t_list_part *part_boot)
  177. {
  178.   t_list_part *element;
  179.   if(part_boot->part->status==STATUS_PRIM_BOOT)
  180.     for(element=list_part;element!=NULL;element=element->next)
  181.     {
  182.       if((element!=part_boot)&&(element->part->status==STATUS_PRIM_BOOT))
  183.     element->part->status=STATUS_PRIM;
  184.     }
  185. }
  186.  
  187. t_list_part *search_part(t_param_disk *disk_car, const int paranoid, const int debug, const int dump_ind, const int fast_mode,const int interface)
  188. {
  189.   int ind_stop=FALSE;
  190.   t_CHS start;
  191.   t_list_part *list_part=NULL;
  192.   t_diskext *partition=partition_new();
  193.   if(interface!=0)
  194.   {
  195.     wmove(stdscr,22,0);
  196.     wstandout(stdscr);
  197.     waddstr(stdscr,"  Stop  ");
  198.     wstandend(stdscr);
  199.   }
  200.   aff_buffer(BUFFER_RESET,"Q");
  201.   ecrit_rapport("\nsearch_part()\n");
  202.   ecrit_rapport("%s",disk_car->description(disk_car));
  203.   /* ncurses: getch will be a non-blocking call */
  204.   for(start.cylinder=0,start.head=1;(start.cylinder<=disk_car->CHS.cylinder)&&(ind_stop==0);start.cylinder++,start.head=0)
  205.   {
  206.     if(interface!=0)
  207.     {
  208.       wmove(stdscr,ANALYSE_Y,ANALYSE_X);
  209.       wclrtoeol(stdscr);
  210.       wdoprintf(stdscr,"Analyse cylinder %5u/%u",start.cylinder,disk_car->CHS.cylinder);
  211.       wrefresh(stdscr);
  212.       switch(wgetch_nodelay(stdscr))
  213.       {
  214.     case KEY_ENTER:
  215. #ifdef PADENTER
  216.     case PADENTER:
  217. #endif
  218.     case '\n':
  219.     case '\r':
  220.     case 's':
  221.     case 'S':
  222.       ind_stop=1;
  223.       break;
  224.       }
  225.     }
  226.     for(;(start.head<=disk_car->CHS.head);start.head++)
  227.     {
  228.       unsigned int sector_inc;
  229.       int part_offset;
  230.       for(start.sector=1,sector_inc=1,part_offset=0;(start.sector<=disk_car->CHS.sector);start.sector+=sector_inc)
  231.       {
  232.     int res=0;
  233.     partition_reset(partition);    /* must not reset lba */
  234.     partition->lba=CHS2LBA(disk_car,&start);
  235.     if((start.sector==1) && ((start.head<=2)||(fast_mode==2)))
  236.     {
  237.       part_offset++;
  238.       switch(part_offset)
  239.       {
  240.         case 1:
  241.           res=search_type_128(disk_car,partition,debug,dump_ind);
  242.           sector_inc=0;
  243.           break;
  244.         case 2:
  245.           res=search_type_2(disk_car,partition,debug,dump_ind);
  246.           break;
  247.         case 3:
  248.           res=search_type_1(disk_car,partition,debug,dump_ind);
  249.           break;
  250.         case 4:
  251.           res=search_type_0(disk_car,partition,debug,dump_ind);
  252.           sector_inc=1;
  253.           break;
  254.         default:
  255.           ecrit_rapport("\nBUG: unusual value of part_offset\n");
  256.           break;
  257.       }
  258.     }
  259.     else
  260.       if(start.sector==7 && fast_mode>0 && ((start.head<=2)||(fast_mode==2)))
  261.       {
  262.         res=search_FAT_backup(disk_car,partition,debug,dump_ind);
  263.       }
  264.       else
  265.         if(start.sector==disk_car->CHS.sector && fast_mode>0)
  266.         {
  267.           if((start.head==disk_car->CHS.head)||(fast_mode>1))
  268.           {
  269.         res=search_NTFS_backup(disk_car,partition,debug,dump_ind);
  270.           }
  271.         }
  272.     if(res<0)
  273.     {
  274.       if(interface!=0)
  275.       {
  276.         wdoprintf(stdscr,msg_READ_ERROR_AT, start.cylinder,start.head,start.sector,partition->lba);
  277.       }
  278.     }
  279.     if(res<=0 && paranoid!=0)
  280.     {
  281.       int s_log_block_size;
  282.       dword ref_lba=partition->lba;
  283.       /* try backup superblock */
  284.       /* It must be in paranoid mode because it can hide otherwise other partition type */
  285.       /* Block size: 1024, 2048 or 4096 bytes (8192 bytes on Alpha systems) */
  286.       /* From e2fsprogs-1.34/lib/ext2fs/initialize.c: set_field(s_first_data_block, super->s_log_block_size ? 0 : 1); */
  287.       /* Assumes that TestDisk is not running under Alpha and s_blocks_per_group=8 * block size */
  288.       for(s_log_block_size=0;(s_log_block_size<=2)&&(res<1);s_log_block_size++)
  289.       {
  290.         /* sparse superblock feature: The groups chosen are 0, 1 and powers of 3, 5 and 7. */
  291.         /* Checking group 3 */
  292.         const dword hd_offset=3*(EXT2_MIN_BLOCK<<s_log_block_size)*8*(EXT2_MIN_BLOCK_SIZE<<s_log_block_size)+(s_log_block_size==0?2:0);
  293.         if(ref_lba>(3*(EXT2_MIN_BLOCK<<s_log_block_size)*8*(EXT2_MIN_BLOCK_SIZE<<s_log_block_size)) &&
  294.          LBA2sector(disk_car,ref_lba-hd_offset)==1 &&  
  295.          (LBA2head(disk_car,ref_lba-hd_offset)<=2 || fast_mode==2))
  296.         {
  297.           unsigned char buffer[2*SECTOR_SIZE];
  298. /*      unsigned int block_size=(EXT2_MIN_BLOCK_SIZE<<s_log_block_size); */
  299. /*      ecrit_rapport("CHS %u/%u/%u %lu %u res=%d\n",start.cylinder,start.head,start.sector,partition->lba,part_offset,res); */
  300. /*      ecrit_rapport("Block size=%u Group %u Backup superblock at %u ?\n",EXT2_MIN_BLOCK_SIZE<<s_log_block_size,group,group*s_blocks_per_group); */
  301.           if(disk_car->read(disk_car,2, &buffer, ref_lba)==0)
  302.           {
  303.         const struct ext2_super_block *sb=(const struct ext2_super_block*)&buffer;
  304.         if(le16(sb->s_block_group_nr)>0)
  305.         {
  306.           if(recover_EXT2(disk_car,sb,partition,debug,dump_ind)==0)
  307.             res=1;
  308.         }
  309.           }
  310.           else
  311.           {
  312.         res=-1;
  313.           }
  314.         }
  315.       }
  316.     }
  317.     if(res<=0 && fast_mode>1)
  318.     {
  319.       /* Because this superblock is at the end of the partition, you should be
  320.        * in slow mode to find it... */
  321.       unsigned char buffer[8*SECTOR_SIZE];
  322.       if(disk_car->read(disk_car,8, &buffer, partition->lba)!=0)
  323.       {
  324.         res=-1;
  325.       }
  326.       else
  327.       {
  328.         if(recover_MD(disk_car,(const struct mdp_superblock_s*)&buffer,partition,debug,dump_ind)==0)
  329.           res=1;
  330.         else
  331.           res=0;
  332.       }
  333.     }
  334.     if(res>0)
  335.     {
  336.       if(partition->part_type!=0 && is_extended(partition->part_type)==0 && partition->part_size>1 && partition->lba>0)
  337.       {
  338.         dword pos_fin=partition->lba+partition->part_size-1;
  339.         aff_part_rapport(disk_car,partition);
  340.         if(pos_fin<=disk_car->size)
  341.         {
  342.           t_diskext *new_partition=partition_new();
  343.           dup_t_diskext(new_partition,partition);
  344.           new_partition->status=STATUS_DELETED;
  345.           /*        check_part(disk_car,debug,new_partition); */
  346.           aff_part_buffer(AFF_PART_NL,disk_car,new_partition);
  347.           list_part=insert_new_partition(list_part,new_partition);
  348.           if(interface)
  349.           {
  350.         aff_buffer(BUFFER_SHOW,"Q");
  351.           }
  352.           if((paranoid==0) && (partition->lba+partition->part_size-1> CHS2LBA(disk_car,&start)))
  353.           {
  354.         LBA2CHS(disk_car,partition->lba+partition->part_size-1,&start);
  355.         part_offset=0;
  356.         sector_inc=1;
  357.           }
  358.         } else {
  359.           if(debug>0)
  360.           {
  361.         aff_part_rapport(disk_car,partition);
  362.         if(pos_fin>disk_car->size)
  363.         {
  364.           ecrit_rapport("This partition ends after the disk limits. ");
  365.         }
  366.         ecrit_rapport("(start=%lu, size=%lu, end=%lu, disk end=%lu)\n",
  367.             partition->lba,partition->part_size, pos_fin,disk_car->size);
  368.           }
  369.         }
  370.       }
  371.     }
  372.       }
  373.     }
  374.   }
  375.   FREE(partition);
  376.   return list_part;
  377. }
  378.  
  379. static void init_part_order(t_list_part *list_part)
  380. {
  381.   int nbr_log=0;
  382.   int nbr_prim=0;
  383.   t_list_part *element;
  384.   for(element=list_part;element!=NULL;element=element->next)
  385.   {
  386.     switch(element->part->status)
  387.     {
  388.       case STATUS_PRIM:
  389.       case STATUS_PRIM_BOOT:
  390.       case STATUS_EXT:
  391.     element->part->order=++nbr_prim;
  392.     break;
  393.       case STATUS_LOG:
  394.     element->part->order=(++nbr_log)+4;
  395.     break;
  396.       default:
  397.     ecrit_rapport("init_part_order: severe error\n");
  398.     break;
  399.     }
  400.   }
  401. }
  402.  
  403. static void ask_mbr_order(t_param_disk *disk_car,t_list_part *list_part)
  404. {
  405.   t_diskext *table[4];
  406.   t_diskext *table2[4];
  407.   int nbr_prim=0;
  408.   int i,pos=0;
  409.   int res;
  410.   int car;
  411.   int quit=0;
  412.   t_list_part *element;
  413.   /* Initialisation */
  414.   aff_copy(stdscr);
  415.   wmove(stdscr,4,0);
  416.   wdoprintf(stdscr,"%s",disk_car->description(disk_car));
  417.   mvwaddstr(stdscr,5,0,msg_MBR_ORDER);
  418.   mvwaddstr(stdscr,6,0,msg_PART_HEADER2);
  419.   for(element=list_part;element!=NULL;element=element->next)
  420.   {
  421.     if((element->part->order>0) && (element->part->order<5))
  422.       table[nbr_prim++]=element->part;
  423.   }
  424.   /* */
  425.   ecrit_rapport("\nSelection des partitions primaires\n");
  426.   for(i=0;i<nbr_prim;i++)
  427.       aff_part_rapport(disk_car,table[i]);
  428.   /* */
  429.   do
  430.   {
  431.     unsigned int order;
  432.     /* sort table into table2 */
  433.     int part=0;
  434.     res=0;
  435.     for(order=1;order<=4;order++)
  436.     {
  437.       int nbr=0;
  438.       for(i=0;i<nbr_prim;i++)
  439.     if(table[i]->order==order)
  440.     {
  441.       table2[part++]=table[i];
  442.       nbr++;
  443.     }
  444.       res|=(nbr>1);
  445.     }
  446.     if(part!=nbr_prim)
  447.     {
  448.       ecrit_rapport("\nBUG part %d, nbr_prim %d\n", part, nbr_prim);
  449.     }
  450.     /* */
  451.     for(i=0;i<nbr_prim;i++)
  452.     {
  453.       wmove(stdscr,5+2+i,0);
  454.       wclrtoeol(stdscr);
  455.       if(i==pos)
  456.     standout();
  457.       aff_part(stdscr,AFF_PART_ORDER,disk_car,table2[i]);
  458.       if(i==pos)
  459.     standend();
  460.     }
  461.     wmove(stdscr,20,0);
  462.     if(res)
  463.       wdoprintf(stdscr,msg_MBR_ORDER_BAD);
  464.     else
  465.       wdoprintf(stdscr,msg_MBR_ORDER_GOOD);
  466.     wrefresh(stdscr);
  467.     car=wgetch(stdscr);
  468.     quit=0;
  469.     switch(car)
  470.     {
  471.       case KEY_UP:
  472.     if(--pos<0)
  473.       pos=nbr_prim-1;
  474.     break;
  475.       case KEY_DOWN:
  476.     if(++pos>=nbr_prim)
  477.       pos=0;
  478.     break;
  479.       case KEY_PPAGE:
  480.     pos=0;
  481.     break;
  482.       case KEY_NPAGE:
  483.     pos=nbr_prim-1;
  484.     break;
  485.       case '1':
  486.       case '2':
  487.       case '3':
  488.       case '4':
  489.     table2[pos]->order=car-'0';
  490.     break;
  491.       case KEY_RIGHT:
  492.       case ' ':
  493.       case '+':
  494.     if(++table2[pos]->order>4)
  495.       table2[pos]->order=1;
  496.     break;
  497.       case KEY_LEFT:
  498.       case '-':
  499.     if(--table2[pos]->order<1)
  500.       table2[pos]->order=4;
  501.     break;
  502.       case 'q':
  503.       case '\r':
  504.       case '\n':
  505.       case KEY_ENTER:
  506. #ifdef PADENTER
  507.       case PADENTER:
  508. #endif
  509.       case 'M':
  510.     quit=1;
  511.     break;
  512.     }
  513.     wrefresh(stdscr);
  514.   } while(res!=0 || quit==0);
  515. }
  516.  
  517.  
  518. static t_list_part *reduce_structure(t_list_part *list_part)
  519.   t_list_part *element=list_part;
  520.   t_list_part *prev=NULL;
  521.   while(element)
  522.   {
  523.     t_list_part *next=element->next;
  524.     if(element->part->status==STATUS_DELETED)
  525.     {
  526.       if(prev==NULL)
  527.     list_part=next;
  528.       else
  529.     prev->next=next;
  530.       if(next!=NULL)
  531.     next->prev=prev;
  532.       FREE(element->part);
  533.       FREE(element);
  534.     }
  535.     else
  536.       prev=element;
  537.     element=next;
  538.   }
  539.   return list_part;
  540. }
  541.  
  542. static t_list_part *add_ext_part(t_param_disk *disk_car, t_list_part *list_part, const int max_ext)
  543. {
  544.   /* list_part need to be sorted! */
  545.   /* All extended partitions of an P_EXTENDX are P_EXTENDED */
  546.   t_list_part *element;
  547.   t_list_part *deb=NULL;
  548.   t_list_part *fin=NULL;
  549.   int nbr_entries=0;
  550.   t_CHS start,end;
  551.   t_diskext *new_partition;
  552.   for(element=list_part;element!=NULL;element=element->next)
  553.   {
  554.     if(element->part->status==STATUS_LOG)
  555.     {
  556.       if(deb==NULL)
  557.       {
  558.     deb=element;
  559.     nbr_entries++;
  560.       }
  561.       fin=element;
  562.     }
  563.     else
  564.       nbr_entries++;
  565.   }
  566.   if(deb==NULL)
  567.     return list_part;
  568.   start.sector=1;
  569.   if((nbr_entries==4)||(max_ext!=0))
  570.   {
  571.     start.cylinder=(deb->prev==NULL?1:LBA2cylinder(disk_car,deb->prev->part->lba+deb->prev->part->part_size-1)+1);
  572.     start.head=0;
  573.     end.cylinder=(fin->next==NULL?disk_car->CHS.cylinder:LBA2cylinder(disk_car,fin->next->part->lba)-1); /* 8 october 2002 */
  574.     end.head=disk_car->CHS.head;
  575.     end.sector=disk_car->CHS.sector;
  576.   }
  577.   else
  578.   {
  579.     start.cylinder=LBA2cylinder(disk_car,deb->part->lba);
  580.     if(LBA2head(disk_car,deb->part->lba)==0)
  581.       ecrit_rapport("BUG while creating a minimal extended partition\n");
  582.     start.head=LBA2head(disk_car,deb->part->lba)-1;
  583.     end.cylinder=LBA2cylinder(disk_car,fin->part->lba+fin->part->part_size-1);
  584.     end.head=disk_car->CHS.head;
  585.     end.sector=disk_car->CHS.sector;
  586.   }
  587.   new_partition=partition_new();
  588.   new_partition->part_type=(end.cylinder>1023?P_EXTENDX:P_EXTENDED);
  589.   new_partition->status=STATUS_EXT;
  590.   new_partition->lba=CHS2LBA(disk_car,&start);
  591.   new_partition->part_size=CHS2LBA(disk_car,&end)-new_partition->lba+1;
  592.   return insert_new_partition(list_part, new_partition);
  593. }
  594.  
  595. static int write_mbr(t_param_disk *disk_car, const t_list_part *list_part, const int ro, const int debug)
  596. {
  597.   const t_list_part *element;
  598.   unsigned char buffer[SECTOR_SIZE];
  599.   unsigned char buffer_org[SECTOR_SIZE];
  600.   if(debug)
  601.     ecrit_rapport("\nwrite_mbr: starting...\n");
  602.   if(read_MBR(disk_car,&buffer_org)) return 1;
  603.   memset((void *)&buffer,0,SECTOR_SIZE);
  604.   if((buffer_org[0x1FE]==0x55) && (buffer_org[0x1FF]==0xAA))
  605.   {
  606.     memcpy(buffer,buffer_org,TAB_PART);
  607.     buffer[0x1FE]=0x55;
  608.     buffer[0x1FF]=0xAA;
  609.   } else {
  610.     write_MBR_code_aux(buffer);
  611.   }
  612.   for(element=list_part;element!=NULL;element=element->next)
  613.   {
  614.     switch(element->part->status)
  615.     {
  616.       case STATUS_PRIM:
  617.       case STATUS_PRIM_BOOT:
  618.       case STATUS_EXT:
  619.     if((element->part->order>=1) && (element->part->order<=4))
  620.     {
  621.       partition2entry(disk_car,0,element->part, 
  622.           pt_offset(buffer,element->part->order-1));
  623.     }
  624.     break;
  625.       case STATUS_LOG:
  626.     break;
  627.       default:
  628.     ecrit_rapport("write_mbr: severe error\n");
  629.     break;
  630.     }
  631.   }
  632.   if(debug>1)
  633.   {
  634.     int i;
  635.     for(i=0;i<4;i++)
  636.     {
  637.       const struct partition_dos *p=pt_offset(buffer,i);
  638.       aff_entry_rapport(p);
  639.     }
  640.     diff(buffer,buffer_org);
  641.   }
  642.   if(ro==0)
  643.     return write_MBR(disk_car,&buffer);
  644.   return 0;
  645. }
  646.  
  647. static int diff(const unsigned char buffer[SECTOR_SIZE], const unsigned char buffer_org[SECTOR_SIZE])
  648. {
  649.   int j;
  650.   if(memcmp(buffer,buffer_org,SECTOR_SIZE))
  651.   {
  652.     ecrit_rapport("\nSectors are different.\n");
  653.     ecrit_rapport("buffer_org\n");
  654.     for(j=0;j<4;j++)
  655.     {
  656.       const struct partition_dos *p=pt_offset_const(buffer_org,j);
  657.       if(p->sys_ind!=0)
  658.     aff_entry_rapport(p);
  659.     }
  660.     ecrit_rapport("buffer\n");
  661.     for(j=0;j<4;j++)
  662.     {
  663.       const struct partition_dos *p=pt_offset_const(buffer,j);
  664.       if(p->sys_ind!=0)
  665.     aff_entry_rapport(p);
  666.     }
  667.     for(j=0;j<SECTOR_SIZE;j++)
  668.       if(buffer_org[j]!=buffer[j])
  669.     ecrit_rapport("%02X %02X %02X\n", j, buffer_org[j], buffer[j]);
  670.     ecrit_rapport("\n");
  671.   }
  672.   return 0;
  673. }
  674.  
  675. static int use_backup(t_param_disk *disk_car, const t_list_part *list_part, const int debug,const int dump_ind)
  676. {
  677.   const t_list_part *element;
  678.   ecrit_rapport("use_backup\n");
  679.   for(element=list_part;element!=NULL;element=element->next)
  680.   {
  681.     if(element->part->boot_sector!=0)
  682.     {
  683.       switch(element->part->upart_type)
  684.       {
  685.     case UP_FAT32:
  686.       fat32_boot_sector(disk_car, element->part, debug, dump_ind);
  687.       break;
  688.     case UP_NTFS:
  689.       ntfs_boot_sector(disk_car, element->part, debug, dump_ind);
  690.       break;
  691.     default:
  692.       ecrit_rapport("Need to fix\n");
  693.       aff_part_rapport(disk_car,element->part);
  694.       break;
  695.       }
  696.     }
  697.   }
  698.   return 0;
  699. }
  700.  
  701. static int write_all_log(t_param_disk *disk_car, const t_list_part *list_part, const int ro, const int debug)
  702. {
  703.   const t_list_part *element;
  704.   const t_list_part *pos_ext=NULL;
  705.   dword current_pos;
  706.   t_diskext *bloc_nextext;
  707.   if(debug)
  708.     ecrit_rapport("write_all_log: starting...\n");
  709.   for(element=list_part;element!=NULL;element=element->next)
  710.   {
  711.     if(element->part->status==STATUS_EXT)
  712.     {
  713.       if(is_extended(element->part->part_type))
  714.       {
  715.     if(pos_ext!=NULL)
  716.       ecrit_rapport("write_all_log: pos_ext already defined\n");
  717.     pos_ext=element;
  718.       }
  719.       else
  720.       {
  721.     ecrit_rapport("write_all_log: STATUS_EXT with bad part_type\n");
  722.       }
  723.     }
  724.   }
  725.   if(pos_ext==NULL)
  726.   {
  727.     wdoprintf(stdscr,msg_NO_EXT_PART);
  728.     return 1;
  729.   }
  730.   current_pos=pos_ext->part->lba;
  731.   bloc_nextext=(t_diskext *)MALLOC(sizeof(*bloc_nextext));
  732.   bloc_nextext->part_type=P_EXTENDED;       /* Never P_EXTENDX */
  733.   if(pos_ext->next==NULL || (pos_ext->next->part->status!=STATUS_LOG))
  734.   {
  735.     unsigned char buffer[SECTOR_SIZE];
  736.     unsigned char buffer_org[SECTOR_SIZE];
  737.     if(debug)
  738.     {
  739.       ecrit_rapport("write_all_log: CHS: %u/%u/%u,lba=%lu\n", LBA2cylinder(disk_car,current_pos), LBA2head(disk_car,current_pos), LBA2sector(disk_car,current_pos),current_pos);
  740.     }
  741.     if(disk_car->read(disk_car,1, &buffer_org, current_pos))
  742.       return 1;
  743.     memset(buffer,0,SECTOR_SIZE);
  744.     memcpy(buffer,buffer_org,TAB_PART);
  745.     buffer[0x1FE]=0x55;
  746.     buffer[0x1FF]=0xAA;
  747.     if(ro)
  748.     {
  749.       if(debug>1)
  750.     diff(buffer,buffer_org);
  751.     }
  752.     else
  753.     {
  754.       if(disk_car->write(disk_car,1, &buffer, current_pos))
  755.       {
  756.     ecrit_rapport(msg_PART_WR_ERR);
  757.     display_message(msg_PART_WR_ERR);
  758.       }
  759.     }
  760.   }
  761.   else
  762.   {
  763.     for(element=pos_ext->next;(element!=NULL) && (element->part->status==STATUS_LOG);element=element->next)
  764.     {
  765.       int j;
  766.       unsigned char buffer[SECTOR_SIZE];
  767.       unsigned char buffer_org[SECTOR_SIZE];
  768.       if(debug)
  769.       {
  770.     ecrit_rapport("write_all_log: CHS: %u/%u/%u,lba=%lu\n", LBA2cylinder(disk_car,current_pos), LBA2head(disk_car,current_pos), LBA2sector(disk_car,current_pos),current_pos);
  771.       }
  772.       if(disk_car->read(disk_car,1, &buffer_org, current_pos))
  773.     return 1;
  774.       memset(buffer,0,SECTOR_SIZE);
  775.       memcpy(buffer,buffer_org,TAB_PART);
  776.       buffer[0x1FE]=0x55;
  777.       buffer[0x1FF]=0xAA;
  778.       partition2entry(disk_car,current_pos,element->part, pt_offset(buffer,0));
  779.       if(element->next!=NULL && (element->next->part->status==STATUS_LOG))
  780.       { /* Construit le pointeur vers la prochaine partition logique */
  781.     t_CHS nextext_start;
  782.     LBA2CHS(disk_car,element->next->part->lba,&nextext_start);
  783.     nextext_start.head=0;
  784.     nextext_start.sector=1;
  785.     bloc_nextext->lba=CHS2LBA(disk_car,&nextext_start);
  786.     /*      ecrit_rapport("table[i]->next=%p table[i+1]=%p\n",table[i]->next,table[i+1]); */
  787.     bloc_nextext->part_size=(element->next->part->lba+element->next->part->part_size-1)-bloc_nextext->lba+1;
  788.     partition2entry(disk_car,pos_ext->part->lba,bloc_nextext, pt_offset(buffer,1));
  789.       }
  790.       if(ro)
  791.       {
  792.     if(debug>1)
  793.     {
  794.       for(j=0;j<4;j++)
  795.       {
  796.         const struct partition_dos *p=pt_offset(buffer,j);
  797.         if(p->sys_ind!=0)
  798.           aff_entry_rapport(p);
  799.       }
  800.       diff(buffer,buffer_org);
  801.     }
  802.       }
  803.       else
  804.       {
  805.     if(disk_car->write(disk_car,1, &buffer, current_pos))
  806.     {
  807.       ecrit_rapport(msg_PART_WR_ERR);
  808.       display_message(msg_PART_WR_ERR);
  809.     }
  810.       }
  811.       current_pos=bloc_nextext->lba;
  812.     }
  813.   }
  814.   FREE(bloc_nextext);
  815.   return 0;
  816. }
  817.  
  818. static t_list_part *do_recover_cih(t_param_disk *disk_car,t_list_part *list_part,int debug,const int dump_ind)
  819. { /* tab_part need to be sorted */
  820.   if((list_part==NULL) || (LBA2cylinder(disk_car,list_part->part->lba)>0))
  821.   {
  822.     t_CHS start,end;
  823.     t_diskext *partition;
  824.     start.cylinder=0;
  825.     start.head=1;
  826.     start.sector=1;
  827.     dup_t_CHS(&end,&disk_car->CHS);
  828.     if(list_part!=NULL)
  829.     {
  830.       end.cylinder=LBA2cylinder(disk_car,list_part->part->lba)-1;
  831.     }
  832.     partition=partition_new();
  833.     partition->lba=CHS2LBA(disk_car,&start);
  834.     partition->part_size=CHS2LBA(disk_car,&end)-partition->lba+1;
  835.     if(rebuild_FAT_BS(disk_car,partition,debug,dump_ind,1)==0)
  836.     {
  837.       ecrit_rapport("rebuild_FAT_BS Ok\n");
  838.       return insert_new_partition(list_part,partition);
  839.     }
  840.     else
  841.       FREE(partition);
  842.   }
  843.   {
  844.     t_diskext *partition;
  845.     t_list_part *element;
  846.     t_list_part *last=NULL;
  847.     for(element=list_part;element!=NULL;element=element->next)
  848.       last=element;
  849.     if(last!=NULL)
  850.     {
  851.       partition=partition_new();
  852.       partition->lba=last->part->lba+last->part->part_size-1;
  853.       partition->part_size=disk_car->size-partition->lba+1;
  854.       if(rebuild_FAT_BS(disk_car,partition,debug,dump_ind,1)==0)
  855.       {
  856.     ecrit_rapport("rebuild_FAT_BS Ok\n");
  857.     return insert_new_partition(list_part,partition);
  858.       }
  859.       else
  860.     FREE(partition);
  861.     }
  862.   }
  863.   return list_part;
  864. }
  865.  
  866.  
  867. int interface_recovery(t_param_disk *disk_car,int paranoid,const int debug,const int dump_ind, int fast_mode,int align, const int recover_cih,const int ask_part_order, const int max_ext)
  868. {
  869.   int res_interface_write;
  870.   do
  871.   {
  872.     t_list_part *list_part;
  873.     t_list_part *element;
  874.     int can_search_deeper=1;
  875.     aff_copy(stdscr);
  876.     wmove(stdscr,4,0);
  877.     wdoprintf(stdscr,"%s",disk_car->description(disk_car));
  878.     wmove(stdscr,5,0);
  879.     res_interface_write=0;
  880.     if(paranoid==1 && fast_mode==2)
  881.       can_search_deeper=0;
  882.     list_part=search_part(disk_car,paranoid,debug,dump_ind,fast_mode,1);
  883.     if(align)
  884.       align_structure(disk_car,list_part);
  885.     /* Little trick to detect Linux software Raid 1 quickly */
  886.     for(element=list_part;element!=NULL;element=element->next)
  887.     {
  888.       unsigned char buffer[8*SECTOR_SIZE];
  889.       struct mdp_superblock_s *sb=(struct mdp_superblock_s*)&buffer;
  890.       dword offset=MD_NEW_SIZE_SECTORS(element->part->part_size);
  891.       
  892.       if(disk_car->read(disk_car,8, &buffer, element->part->lba+offset)==0)
  893.       {
  894.     t_diskext *new_partition=partition_new();
  895.     dup_t_diskext(new_partition,element->part);
  896.     if(test_MD(disk_car,sb,new_partition,debug,dump_ind)==0)
  897.     {
  898.       set_MD_info(disk_car,sb,new_partition,debug,dump_ind);
  899.       new_partition->part_type=P_RAID;
  900.       new_partition->part_size=(sb->size<<1)+MD_RESERVED_SECTORS;
  901.       list_part=insert_new_partition(list_part,new_partition);
  902.     }
  903.     else
  904.       FREE(new_partition);
  905.       }
  906.     }
  907.     if(align)    /* Need to align new partition */
  908.       align_structure(disk_car,list_part);
  909.     init_structure(disk_car,list_part,debug);
  910. #ifdef DEBUG
  911.     check_list_part(list_part);
  912. #endif
  913.     if(debug)
  914.     {
  915.       /* Ajoute dans le fichier de log les partitions trouvees */
  916.       ecrit_rapport("\nResults\n");
  917.       for(element=list_part;element!=NULL;element=element->next)
  918.     aff_part_rapport(disk_car,element->part);
  919.     }
  920.     wdoprintf(stdscr,msg_GOD_MODE);
  921.     list_part=ask_structure(disk_car,list_part,debug);
  922.     if(test_structure(list_part)==0)
  923.     {
  924.       list_part=reduce_structure(list_part);
  925. #ifdef DEBUG
  926.       check_list_part(list_part);
  927. #endif
  928.       /* Sort list_part */
  929.       list_part=sort_list_part(list_part);
  930. #ifdef DEBUG
  931.       check_list_part(list_part);
  932. #endif
  933.       if(recover_cih)
  934.       {
  935.     list_part=do_recover_cih(disk_car,list_part,debug,dump_ind);
  936.     list_part=sort_list_part(list_part);
  937.       }
  938.       /* Creer la partition etendue globale */
  939.       list_part=add_ext_part(disk_car,list_part,max_ext);
  940.       /*
  941.       ecrit_rapport("\nResults with extended\n");
  942.       for(element=list_part;element;element=element->next)
  943.     aff_part_rapport(disk_car,element->part);
  944.     */
  945.       init_part_order(list_part);
  946.       if(ask_part_order)
  947.       {
  948.     /* Demande l'ordre des entrees dans le MBR */
  949.     ask_mbr_order(disk_car,list_part);
  950.     /* Demande l'ordre des partitions etendues */
  951.       }
  952.       res_interface_write=interface_write(disk_car,list_part,can_search_deeper);
  953.       switch(res_interface_write)
  954.       {
  955.     case 1:
  956.       if(ask_confirmation("Write partition table, confirm ? (Y/N)"))
  957.       {
  958.         ecrit_rapport("write!\n");
  959.         write_mbr(disk_car,list_part,RW,debug);
  960.         write_all_log(disk_car,list_part,RW,debug);
  961.         use_backup(disk_car,list_part,debug,dump_ind);
  962.       }
  963.       else
  964.         ecrit_rapport("Don't write, no confirmation\n");
  965.     break;
  966.     case 0:
  967.     ecrit_rapport("simulate write!\n");
  968.     write_mbr(disk_car,list_part,RO,debug);
  969.     write_all_log(disk_car,list_part,RO,debug);
  970.     break;
  971.     case 2:
  972.     paranoid=1;
  973.     if(fast_mode<2)
  974.       fast_mode++;
  975.     break;
  976.       }
  977.     }
  978.     delete_list_part(list_part);
  979.   } while(res_interface_write==2);
  980.   return 0;
  981. }
  982.